package cn.org.tpeach.nosql.redis.service.impl;

import cn.org.tpeach.nosql.annotation.Component;
import cn.org.tpeach.nosql.constant.ConfigConstant;
import cn.org.tpeach.nosql.constant.PublicConstant;
import cn.org.tpeach.nosql.exception.ServiceException;
import cn.org.tpeach.nosql.framework.LarkFrame;
import cn.org.tpeach.nosql.redis.bean.RedisConnectInfo;
import cn.org.tpeach.nosql.redis.connection.RedisLarkPool;
import cn.org.tpeach.nosql.redis.service.IRedisConfigService;
import cn.org.tpeach.nosql.tools.*;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.*;

/**
 * @author tyz
 * @Title: RedisConfigServiceImpl
 * @ProjectName RedisLark
 * @Description:
 * @date 2020-05-22 22:47
 * @since 1.0.0
 */
@Component(value = "redisConfigService", scope = Component.BeanScope.SCOPE_SINGLETON, lazy = false)
@Slf4j
public class RedisConfigServiceImpl implements IRedisConfigService {
    @Override
    public List<RedisConnectInfo> getRedisConfigAllList() {
        List<RedisConnectInfo> resultList = new LinkedList<>();
        List<Map<String, Map<String, ConfigMapper>>> list = ConfigParserUtils.getInstance().getListBySectionList(ConfigConstant.ConnectList.SECTION);
        if(list == null){
            //初始化
            ConfigParserUtils.getInstance().initList(ConfigConstant.ConnectList.SECTION);
            try {
                ConfigParserUtils.getInstance().flushEntries(LarkFrame.REDIS_CONFIG_PATH);
            } catch (IOException e) {
                log.error("初始化"+ConfigConstant.ConnectList.SECTION+"失败",e);
            }
        }else if(!list.isEmpty()) {
            for (Map<String, Map<String, ConfigMapper>> map : list) {
                for (Map.Entry<String, Map<String, ConfigMapper>> entry : map.entrySet()) {
                    RedisConnectInfo redisConnectInfo = ConfigParserUtils.getInstance().configMapperToBean(ConfigConstant.ConnectList.KEY, entry.getValue(), RedisConnectInfo.class);
                    if(redisConnectInfo != null){
                        redisConnectInfo.setAuth(AESUtil.decrypt(redisConnectInfo.getAuth()));
                        resultList.add(redisConnectInfo);
                    }
                }
            }
        }
        return resultList;
    }



    @Override
    public RedisConnectInfo addRedisConfig(RedisConnectInfo connectInfo) {
        String auth = connectInfo.getAuth();
        if(auth != null){
            connectInfo.setAuth(AESUtil.encrypt(auth));
        }
        connectInfo.setId(StringUtils.simpleRandomUUID());
        Map<String, ConfigMapper> mapperMap = ConfigParserUtils.getInstance().beanToConfigMapper(connectInfo);
        connectInfo.setAuth(auth);
        ConfigParserUtils.getInstance().putList(ConfigConstant.ConnectList.SECTION,ConfigConstant.ConnectList.KEY,mapperMap);
        try {
            ConfigParserUtils.getInstance().flushEntries(LarkFrame.REDIS_CONFIG_PATH);
        } catch (IOException e) {
            log.error("添加连接信息失败" ,e);
            throw new ServiceException("添加连接信息失败");
        }
        return connectInfo;
    }



    @Override
    public RedisConnectInfo deleteRedisConfigById(String id) {
        List<Map<String, Map<String, ConfigMapper>>> list = ConfigParserUtils.getInstance().getListBySectionList(ConfigConstant.ConnectList.SECTION);
        if(DataStructureUtils.isNotEmpty(list)) {
            Iterator<Map<String, Map<String, ConfigMapper>>> iterator = list.iterator();
            while (iterator.hasNext()) {
                Map<String, Map<String, ConfigMapper>> map = iterator.next();
                for (Map.Entry<String, Map<String, ConfigMapper>> entry : map.entrySet()) {
                    String configId = ConfigParserUtils.getInstance().getString(entry.getValue(), ConfigConstant.ConnectList.SECTION, "id", "");
                    if(StringUtils.equals(configId,id)) {
                        iterator.remove();
                        try {
                            ConfigParserUtils.getInstance().flushEntries(LarkFrame.REDIS_CONFIG_PATH);
                        } catch (IOException e) {
                            log.error("删除连接信息失败" ,e);
                            throw new ServiceException("删除连接信息失败");
                        }
                        RedisLarkPool.deleteConnectInfo(id);
                        RedisLarkPool.destory(id);
                        return ConfigParserUtils.getInstance().configMapperToBean(ConfigConstant.ConnectList.KEY,entry.getValue(),RedisConnectInfo.class);
                    }
                }
            }
        }

        return null;
    }
    private Map<String, ConfigMapper> getConfigMapperById(String id){
        if(StringUtils.isNotBlank(id)){
            List<Map<String, Map<String, ConfigMapper>>> listBySectionList = ConfigParserUtils.getInstance().getListBySectionList(ConfigConstant.ConnectList.SECTION);
            if(DataStructureUtils.isNotEmpty(listBySectionList)) {
                for (Map<String, Map<String, ConfigMapper>> map : listBySectionList) {
                    for (Map.Entry<String, Map<String, ConfigMapper>> entry : map.entrySet()) {
                        String configId = ConfigParserUtils.getInstance().getString(entry.getValue(), ConfigConstant.ConnectList.KEY, "id", "");
                        if(configId.equals(id)) {
                            return entry.getValue();
                        }
                    }
                }
            }
        }
        return null;
    }
    @Override
    public RedisConnectInfo getRedisConfigById(String id) {
        Map<String, ConfigMapper> mapper = getConfigMapperById(id);
        if(mapper != null){
            RedisConnectInfo redisConnectInfo = ConfigParserUtils.getInstance().configMapperToBean(ConfigConstant.ConnectList.KEY, mapper, RedisConnectInfo.class);
            if(redisConnectInfo != null){
                redisConnectInfo.setAuth(AESUtil.decrypt(redisConnectInfo.getAuth()));
                return redisConnectInfo;
            }
        }
        return null;
    }

    @Override
    public RedisConnectInfo updateRedisConfig(RedisConnectInfo connectInfo) {
        if(connectInfo == null){
            return null;
        }
        Map<String, ConfigMapper> mapper = getConfigMapperById(connectInfo.getId());
        if(mapper != null){
            String auth = connectInfo.getAuth();
            if(auth != null){
                connectInfo.setAuth(AESUtil.encrypt(auth));
            }
            Map<String, ConfigMapper> mapperMap = ConfigParserUtils.getInstance().beanToConfigMapper(connectInfo);
            mapper.putAll(mapperMap);
            connectInfo.setAuth(auth);
            try {
                ConfigParserUtils.getInstance().flushEntries(LarkFrame.REDIS_CONFIG_PATH);
            } catch (IOException e) {
                log.error("更新连接信息失败" ,e);
                throw new ServiceException("更新连接信息失败");
            }
            RedisLarkPool.addOrUpdateConnectInfo(connectInfo);
            return connectInfo;
        }
        return null;
    }

    @Override
    public void resetConfig() throws IOException {
        ConfigParserUtils.getInstance().getEntries().clear();
        try {
            ConfigParserUtils.getInstance().flushEntries(LarkFrame.REDIS_CONFIG_PATH);
        } catch (IOException e) {
            e.printStackTrace();
        }
        ConfigParserUtils.getInstance().readConfigFile(LarkFrame.REDIS_CONFIG_PATH);
    }

    @Override
    public void moveRedisconfig(RedisConnectInfo conn,RedisConnectInfo targetConn) {
        if(conn == null || targetConn == null){
            return;
        }
        if(getIndex(targetConn) == null){
            return;
        }
        List<Map<String, Map<String, ConfigMapper>>> list = ConfigParserUtils.getInstance().getListBySectionList(ConfigConstant.ConnectList.SECTION);
        if(DataStructureUtils.isNotEmpty(list)) {
            Integer index = null;
            HashMap<String, Map<String, ConfigMapper>> moveElem = null;
            label:
            for (int i = 0; i <list.size() ; i++) {
                Map<String, Map<String, ConfigMapper>> map = list.get(i);
                for (Map.Entry<String, Map<String, ConfigMapper>> entry : map.entrySet()) {
                    Map<String, ConfigMapper> value = entry.getValue();
                    String configId = ConfigParserUtils.getInstance().getString(value, ConfigConstant.ConnectList.KEY, "id", "");
                    if(configId.equals(conn.getId())) {
                        index = i;
                        moveElem = (HashMap<String, Map<String, ConfigMapper>>) map;
                        break label;
                    }
                }
            }
            if(index != null){
                list.remove(moveElem);
                list.add(getIndex(targetConn)+1,moveElem);
                ConfigParserUtils.getInstance().getEntries().put(ConfigConstant.ConnectList.SECTION, list);
                try {
                    ConfigParserUtils.getInstance().flushEntries(LarkFrame.REDIS_CONFIG_PATH);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public Integer getIndex(RedisConnectInfo conn){
        return getIndexById(conn.getId());
    }

    @Override
    public Integer getIndexById(String id) {
        List<Map<String, Map<String, ConfigMapper>>> listBySectionList = ConfigParserUtils.getInstance().getListBySectionList(ConfigConstant.ConnectList.SECTION);
        for (int i = 0; i <listBySectionList.size() ; i++) {
            Map<String, Map<String, ConfigMapper>> map = listBySectionList.get(i);
            for (Map.Entry<String, Map<String, ConfigMapper>> entry : map.entrySet()) {
                Map<String, ConfigMapper> value = entry.getValue();
                String configId = ConfigParserUtils.getInstance().getString(value, ConfigConstant.ConnectList.KEY, "id", "");
                if(configId.equals(id)) {
                    return i;
                }
            }
        }
        return null;
    }
}
